知っているようで意外と知らなかったPython小ネタ集
仕事ではよくPythonを書いています。
よく使うのでそれなりに知っている気になっていたのですが、 コードをレビューしてもらったり本を読んだりしているうちに”もっと早く知っておきたかった・・・”というネタが溜まってきたので、その中から厳選した5つの小ネタをまとめてみました。
*この記事で使用しているPythonのバージョンはPython 3.7.3
です。
この変数、一体何桁?
例えばこんな変数があったとします。
num1 = 100000000 num2 = 10000 num3 = 3023204903
こんな変数がたくさんあったらどうしましょう。
桁を数えるだけで目が疲れそうです。
ぱっと見でだいたい何桁あるかわかるといいですよね。
Pythonでは数値型に_
を挟んでも、そのまま数値として計算することができます。
>>> num1 = 100_000_000 >>> num2 = 10_000 >>> sum = num1 + num2 >>> sum 100010000
そのままいい感じにアンダースコアをセパレータに置き換えたい場合はこのように書くことができます。
>>> f'{sum:,}' '100,010,000'
三項演算子、使っていこう
他の多くの言語同様Pythonでも三項演算子(Ternary Operator)が使えます。
このようなif分岐だと、
condition = True if condition: x = 1 else: x = 2
三項演算子を使って一行でスマートに書くことができます。
condition = True x = 1 if condition else 2
ネストが深い場合はif文を使った方が読みやすい事もあるので うまく使い分けたいですね。
if文 OR 三項演算子?
余談ですが、PythonではConditional Statement(if文)とTernary Operator(三項演算子)は違うのだろうか・・・と気になったので調べてみたところ、ドキュメントのあちこちでTernary Operatorと言っていたり、Conditional Statementと言っていたりしたので明確な線引きはなさそうだという結論に落ち着きました。
Conditional Expressions (Python's Ternary Operator) Python supports one additional decision-making entity called a conditional expression. (It is also referred to as a conditional operator or ternary operator in various places in the Python documentation.) Conditional expressions were proposed for addition to the language in PEP 308 and green-lighted by Guido in 2005.
enumerateって便利
配列をループする際に、Indexが欲しいことがあると思います。
names = ['Tom','Peter','Taro','Chris'] index = 0 for name in names: print(index, name) index +=1
実行結果:
0 Tom 1 Peter 2 Taro 3 Chris
上のように実装することもできますが、enumerateを使うと更にスマートに書くことができます。
names = ['Tom','Peter','Taro','Chris'] for index, name in enumerate(names): print(index, name)
実行結果:
0 Tom 1 Peter 2 Taro 3 Chris
enumerateはキーに数値Indexを割り振ってくれます。
Indexの初めの値を設定するにはstart=1
のオプションをつけます。
for index, name in enumerate(names, start=1): print(index, name)
実行結果:
1 Tom 2 Peter 3 Taro 4 Chris
この特性を使って辞書にenumerateを代入してみると、 キーにIndexが割り当てられいい感じです。
new_dict = dict(enumerate(names)) print(new_dict)
実行結果:
{0: 'Tom', 1: 'Peter', 2: 'Taro', 3: 'Chris', 4: 'Tom'}
zip()
こんなに便利な関数があるのかと感動したのがzip()です。
複数のイテラブルオブジェクトをループしたい時にzip関数はとても便利です。
names = ['Tom','Peter','Taro','Chris'] age = [20, 13, 30, 35] dept = ['Business', 'HR', 'Manager', 'Engineer'] for name, age, dept in zip(names, age, dept): print(f'{name}: {age}: {dept}')
実行結果:
Tom: 20: Business Peter: 13: HR Taro: 30: Manager Chris: 35: Engineer
zipでそれぞれのリストをタプルに変換する
names = ['Tom','Peter','Taro','Chris'] age = [20, 13, 30, 35] dept = ['Business', 'HR', 'Manager', 'Engineer'] for value in zip(names, age, dept): print(value)
実行結果:
('Tom', 20, 'Business') ('Peter', 13, 'HR') ('Taro', 30, 'Manager') ('Chris', 35, 'Engineer')
zip_longest
zipは一番短い配列に合わせて処理を終了するので、長い配列の余った要素が無視されてしまいます。
names = ['Tom','Peter','Taro','Chris'] age = [20, 13] dept = ['Business', 'HR', 'Manager', 'Engineer'] for value in zip(names, age, dept): print(value)
実行結果:
('Tom', 20, 'Business') ('Peter', 13, 'HR') # TaroとChrisがいないよ!
長い配列に合わせたい場合はzipの代わりに
zip_longest()
が使えます。
from itertools import zip_longest names = ['Tom','Peter','Taro','Chris'] age = [20, 13] dept = ['Business', 'HR', 'Manager', 'Engineer'] for value in zip_longest(names, age, dept): print(value)
('Tom', 20, 'Business') ('Peter', 13, 'HR') ('Taro', None, 'Manager') ('Chris', None, 'Engineer') # Good!
足りない分の要素にはデフォルトでNoneが入りますが、
fillvalue
で任意の値を割り当てることもできます。
names = ['Tom','Peter','Taro','Chris'] age = [20, 13] dept = ['Business', 'HR', 'Manager', 'Engineer'] for value in zip_longest(names, age, dept, fillvalue=20): print(value)
実行結果:
('Tom', 20, 'Business') ('Peter', 13, 'HR') ('Taro', 20, 'Management') ('Chris', 20, 'Engineer')
二つの配列を辞書に変換
zipを使って二つの配列をそのまま辞書に代入することもできます。
new_dict = dict(zip_longest(names, age, fillvalue=25))
実行結果:
>>> new_dict = dict(zip_longest(names, age, fillvalue=25)) >>> new_dict {'Tom': 20, 'Peter': 13, 'Taro': 25, 'Chris': 25}
配列の展開
下のコードを実行すると、どうなるでしょう
a, b, c = ['Tom','Peter','Taro','Chris']
エラーになりますね。
配列の値の数に対して変数が足りてないよ、と怒られています。
>>> a, b, c = ['Tom','Peter','Taro','Chris'] Traceback (most recent call last): File "<stdin>", line 1, in <module> ValueError: too many values to unpack (expected 3)
初めと二番目の値のみ欲しいけど、後は別にいらない、という時
最後の変数に*
をつけると巻き取ってくれます。
>>> a, b, *c = ['Tom','Peter','Taro','Chris'] >>> a, b, c ('Tom', 'Peter', ['Taro', 'Chris'])
三番目以降の値が配列になってcに代入されているのがわかります。
1番目と4番目の値だけ欲しい場合はbに*
をつけることで二番目と三番目の値がbに代入されます。
>>> a, *b, c = ['Tom','Peter','Taro','Chris'] >>> a, b, c ('Tom', ['Peter', 'Taro'], 'Chris')
本当に使わない時は変数の代わりに_
にしてしまいましょう。
Pythonでは使っていない変数にWarning
が表示されることがありますが、_
にしておくことで回避することができます。
>>> a, *_, c = ['Tom','Peter','Taro','Chris'] >>> a, c ('Tom','Chris')
あとがき
”もっと早く知っておきたかった・・・!”と思った小ネタをまとめてみました。
特に、zip関数は存在すら知らなかったのでとても勉強になりました。
毎日何かしらの学びがあるのは楽しいですね。
この記事が少しでも誰かの役に立てれば嬉しいです。